Design Patterns in .NET by Dmitri Nesteruk

Design Patterns in .NET by Dmitri Nesteruk

Author:Dmitri Nesteruk
Language: eng
Format: mobi, epub
ISBN: 9781484243664
Publisher: Apress
Published: 2019-05-12T10:58:36.832580+00:00


Just to be safe, we force GC at this point.

Finally, we use the dotMemory unit testing API to output the total amount of memory taken up by the program.

Running this entirely unscientific (but indicative) test on my machine tells me that the User2 implementation saves us 329,305 bytes. Is this significant? Well, let’s calculate: a single ten-character string takes up 34 bytes (14 bytes1 + 2 × 10 bytes for the letters), so 340,000 bytes for all the strings. This means we reduced the amount of memory taken by 97 percent! If this isn’t cause for celebration, I don’t know what is.

Text Formatting

Let’s say you are working with a text editor, and you want to add formatting to text—for example, make text bold, make text italic, or capitalize it. How would you do this? One option is to treat each character individually: if your text is composed of X characters, you make a bool array of size X and simply flip each of the flags if you want to alter text. This would lead to the following implementation:

public class FormattedText

{

private string plainText;

public FormattedText(string plainText)

{

this.plainText = plainText;

capitalize = new bool[plainText.Length];

}

public void Capitalize(int start, int end)

{

for (int i = start; i <= end; ++i)

capitalize[i] = true;

}

private bool[] capitalize;

}

I am using capitalization here (because that’s what a text console can render), but you can think of other forms of formatting being here, too. For every type of formatting, you would be making another Boolean array, initializing it to the right size in the constructor (and imagine the nightmare if the text changes), and then, of course, you would need to take into account those Boolean flags whenever you actually want to show the text somewhere:

public override string ToString()

{

var sb = new StringBuilder();

for (var i = 0; i < plainText.Length; i++)

{

var c = plainText[i];

sb.Append(capitalize[i] ? char.ToUpper(c) : c);

}

return sb.ToString();

}

This approach does in fact work:

var ft = new FormattedText("This is a brave new world");

ft.Capitalize(10, 15);

WriteLine(ft); // This is a BRAVE new world

Of course, we are wasting memory. Even if the text has no formatting whatsoever, we still allocated the array. True, we could have made it lazy so that it is only created whenever someone uses the Capitalize() method , but then we would still lose a lot of memory on first use, particularly with large texts.

This is precisely the situation for which the Flyweight design pattern is made. In this particular case, we’re going to define a Flyweight as a Range class that stores information about the start and end position of a substring within a string, as well as all the formatting information we desire:

public class TextRange

{

public int Start, End;

public bool Capitalize; // also Bold, Italic, etc.

public bool Covers(int position)

{

return position >= Start && position <= End;

}

}

Now, we can define a BetterFormattedText class that simply stores a list of all the formatting that was applied:

public class BetterFormattedText

{

private readonly string plainText;

private readonly List<TextRange> formatting

= new List<TextRange>();

public BetterFormattedText(string plainText)

{

this.plainText = plainText;

}

public TextRange GetRange(int start, int end)

{

var range = new TextRange {Start = start, End = end};

formatting.



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.